#coding=utf-8
import pygame
import sys
import os
import myplane
import bullet
import enemy
import supply
from pygame.locals import *
from random import *
from memory_pic import *
from base64 import *
from threading import Thread
import zmq
import warnings
warnings.filterwarnings("ignore")
sys.path.append('..')

# 游戏思路：先不考虑背景音乐，实现单人模式代码，再以单人模式为基础添加双人模式并修复一些问题
# 1.init后设置bg_size, screen, caption，background_image 等，主模块先实现基本循环，绘制背景，设置延时，刷新画面
# 2.通过myplane模块设置Myplane这一己方飞机的类，设置基本属性image, rect, width, height, speed与基本方法move
# 3.响应键盘，添加事件检测，借助get_pressed()方法处理频繁触发的按键事件
# 4.通过图片切换设置动画效果，设置delay变量进行延时
# 5.通过enemy模块设置由小到大三种敌机，基本属性与己方飞机相似，但move方法只有rect.top以一定速度增加,并添加敌机死亡后的reset方法
# 6.对中、大型敌机设置特定的飞行动画，再main中实例化三种敌机，写成添加敌机、增加敌机速度的函数以备调用，产生enemies，xxx_enemies共4个组待后续检测
# 7.在画面上绘制大型、中型、小型敌机，screen.blit()即可
# 8.碰撞检测（为待检测类添加mask属性）：己方飞机与敌机；在myplane中设置坠毁动画及索引，实现整组播放后reset
# 9.为各个类添加active属性，绘制飞机时分类讨论，active则正常图片，not active则使用碰撞图片
# 10.发射子弹（先设置两种）单独定义bullet模块，属性方法与小型敌机类似，在主模块中实例化子弹，存为bullet列表，设置延时，确定发射频率
# 11.检测子弹是否击中敌机，即遍历bullet列表，判断其与enemies这一group的碰撞情况
# 12.为中型与大型敌机设置energy变量及血槽提醒
# 13.为敌机添加中弹效果，方法与此前的几种动画类似
# 14.绘制得分，在每次播放完一轮中弹动画后，实现score的增加（font对象）
# 15.暂停游戏，设置paused变量，检测鼠标位置,绘制界面时讨论pasued与否
# 16.通过level变量及此前完成的添加敌机、敌机加速函数，实现在一定分数时难度的增加
# 17.设置全屏炸弹，空格键触发，在屏幕以内（bottom > 0）的敌机active = False
# 18.通过补给包发放bullet或bomb，设置为单独supply模块，有bullet_supply和bomb_supply两类
# 19.实例化补给包，并设置发放的时间间隔，定时触发，通过随机值选择补给类型，若为炸弹，则小于上限时可增加，若为子弹，则设置有效时间
# 20.使用set_timer，设置is_double_bullet = True or False(得到后为True,时间到后为False)，暂停时停止计时
# 21.绘制补给包并通过碰撞检测是否获得
# 22.绘制两种子弹，方法类似，注意位置，讨论是否为double
# 23.设置三次机会，绘制life图片，设置life_num变量，在循环条件中加入life_num > 0
# 24.设置重生后的invincible_time，方法与此前类似，在Myplane中添加active属性与reset方法
# 25.绘制结束画面，包含最高分及本次得分，重新开始及结束游戏，最高分使用文件操作，而两个按钮原理为检测鼠标点击位置
# 后续：
# 1.打包为exe文件屡次失败，原因为安装了错误位数的pywin32
# 2.希望实现单独exe运行，将所有文件转为memory源码进行import，使用前get临时文件，最后删除
# 3.在打包2048闪退后发现，游戏中所用的字体若非arial一定要以文件的形式导入，而不能直接在Font中设置字体，字体为None同样无法打包
# 4.添加了三发子弹，把双发设为永久，三发限时（重生时变为单发）
# 5.后续添加双人模式，出现些许bug：（采用比较暴力的复制粘贴法，以单人模式为基础，添加一个类实例me_mate）
    # 1）封面绘制时遗忘pygame.display.flip()，封面动画绘制时在循环体内生成plane_gif，导致动画间断
    # 2）本方飞机绘制时两飞机位置重合
    # 3）双人模式添加队友飞机功能时屡次出现遗漏
    # 4）单人模式受到双人模式“虚拟飞机”影响，is_single变量没有统一在每次碰撞检测中加入导致“空气抢走了我的包”“敌机撞上空气等”
    # 5）双人模式中两飞机重合时的bug（改为2号获得子弹包，2号承受伤害）
    # 6) 解决问题5时设置了me_life_num > 0才存在的局部变量me_get，导致错误
    # 7）解决问题5的承受伤害问题时设置me.active = True时1号才会承受伤害，导致2号玩家出局后1号处于无敌状态
# 6.添加暂停快捷键，注意暂停后补给包时间也要停止计算
# 7.添加背景音乐与对应音效，设置silence变量以实现静音快捷键

GESTURE_MODE = 1
up, down, left, right = 0, 0, 0, 0
up_3, down_3, left_3, right_3 = 0, 0, 0, 0
boom_value, boom_3_value, count_boom = 0, 0, 0
gap = 0

def get_pic(pic_code, pic_name):
    image = open(pic_name, 'wb')
    image.write(b64decode(pic_code))
    image.close()


get_pic(again_png, "again.png")
get_pic(background_png, "background.png")
get_pic(bomb_png, "bomb.png")
get_pic(gameover_png, "gameover.png")
get_pic(life_png, "life.png")
get_pic(life_new_png, "life_new.png")
get_pic(life_new_mate_png, "life_new_mate.png")
get_pic(pause_nor_png, "pause_nor.png")
get_pic(pause_pressed_png, "pause_pressed.png")
get_pic(resume_nor_png, "resume_nor.png")
get_pic(resume_pressed_png, "resume_pressed.png")
get_pic(font_ttf, "font.ttf")
get_pic(bullet_wav, "bullet.wav")
get_pic(enemy1_down_wav, "enemy1_down.wav")
get_pic(enemy2_down_wav, "enemy2_down.wav")
get_pic(enemy3_down_wav, "enemy3_down.wav")
get_pic(enemy3_flying_wav, "enemy3_flying.wav")
get_pic(get_bomb_wav, "get_bomb.wav")
get_pic(get_bullet_wav, "get_bullet.wav")
get_pic(me_down_wav, "me_down.wav")
get_pic(supply_wav, "supply.wav")
get_pic(upgrade_wav, "upgrade.wav")
get_pic(use_bomb_wav, "use_bomb.wav")
get_pic(game_music_ogg, "game_music.ogg")
if not os.path.exists("record1.txt"):
    get_pic(record1_txt, "record1.txt")
if not os.path.exists("record2.txt"):
    get_pic(record2_txt, "record2.txt")

pics = ["again.png", "background.png", "bomb.png", "bomb_supply.png",
        "bullet_supply.png", "bullet1.png", "bullet2.png", "bullet3.png", "enemy1.png",
        "enemy1_down1.png", "enemy1_down2.png", "enemy1_down3.png",
        "enemy1_down4.png", "enemy2.png", "enemy2_down1.png", "enemy2_down2.png",
        "enemy2_down3.png", "enemy2_down4.png", "enemy2_hit.png", "enemy3_n1.png",
        "enemy3_n2.png", "enemy3_down1.png", "enemy3_down2.png", "enemy3_down3.png",
        "enemy3_down4.png", "enemy3_down5.png", "enemy3_down6.png", "enemy3_hit.png",
        "gameover.png", "life.png", "life_new.png", "life_new_mate.png", "me_destroy_1.png", "me_destroy_2.png",
        "me_destroy_3.png", "me_destroy_4.png", "me1.png", "me2.png", "pause_nor.png",
        "pause_pressed.png", "resume_nor.png", "resume_pressed.png",
        "bullet.wav", "enemy1_down.wav", "enemy2_down.wav",
        "enemy3_down.wav", "enemy3_flying.wav", "get_bomb.wav", "get_bullet.wav",
        "me_down.wav", "supply.wav", "upgrade.wav", "use_bomb.wav", "game_music.ogg"]

pygame.init()
pygame.mixer.init()
bg_size = [480, 670]
width = 480
height = 670
screen = pygame.display.set_mode(bg_size)
pygame.display.set_caption('Game: Plane')
background = pygame.image.load('background.png').convert_alpha()
# 设置颜色常量
BLACK = (0, 0, 0)
DARK_GREEN = (60, 85, 60)
GREEN = (0, 255, 0)
RED = (200, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 200)
# 载入游戏音乐及音效
silence = False
pygame.mixer.music.load('game_music.ogg')
pygame.mixer.music.set_volume(0.1)
bullet_sound = pygame.mixer.Sound('bullet.wav')
bullet_sound.set_volume(0.1)
bomb_sound = pygame.mixer.Sound("use_bomb.wav")
bomb_sound.set_volume(0.2)
supply_sound = pygame.mixer.Sound("supply.wav")
supply_sound.set_volume(0.2)
get_bomb_sound = pygame.mixer.Sound("get_bomb.wav")
get_bomb_sound.set_volume(0.2)
get_bullet_sound = pygame.mixer.Sound("get_bullet.wav")
get_bullet_sound.set_volume(0.2)
upgrade_sound = pygame.mixer.Sound("upgrade.wav")
upgrade_sound.set_volume(0.2)
enemy3_fly_sound = pygame.mixer.Sound("enemy3_flying.wav")
enemy3_fly_sound.set_volume(0.2)
enemy1_down_sound = pygame.mixer.Sound("enemy1_down.wav")
enemy1_down_sound.set_volume(0.2)
enemy2_down_sound = pygame.mixer.Sound("enemy2_down.wav")
enemy2_down_sound.set_volume(0.5)
enemy3_down_sound = pygame.mixer.Sound("enemy3_down.wav")
enemy3_down_sound.set_volume(0.5)
me_down_sound = pygame.mixer.Sound("me_down.wav")
me_down_sound.set_volume(0.3)


# 选择模式
def mode_choice(screen):
    mode_text = pygame.font.Font('font.ttf', 48)
    # pygame.draw.rect(screen, DARK_GREEN, [150, 200, 150, 100], 4)
    # pygame.draw.rect(screen, DARK_GREEN, [150, 310, 150, 100], 4)
    mode_text1 = mode_text.render("Single", True, WHITE)
    mode_text2 = mode_text.render("Double", True, WHITE)
    screen.blit(mode_text1, [170, 220])
    screen.blit(mode_text2, [160, 330])


# 添加敌方飞机
def add_small_enemies(group1, group2, num):
    for i in range(num):
        e1 = enemy.SmallEnemy(bg_size)
        group1.add(e1)
        group2.add(e1)


def add_mid_enemies(group1, group2, num):
    for i in range(num):
        e2 = enemy.MidEnemy(bg_size)
        group1.add(e2)
        group2.add(e2)


def add_big_enemies(group1, group2, num):
    for i in range(num):
        e3 = enemy.BigEnemy(bg_size)
        group1.add(e3)
        group2.add(e3)


# 飞机加速
def inc_speed(target, inc):
    for each in target:
        each.speed += inc


def plane_main():
    global silence
    if not silence:
        pygame.mixer.music.play(-1)
    # 生成己方飞机
    me = myplane.MyPlane(bg_size)
    me_mate = myplane.MyPlane_Mate(bg_size)
    text_number = pygame.font.Font('font.ttf', 16)
    me_number = text_number.render('2', True, BLUE)
    mate_number = text_number.render('1', True, RED)
    # 生命数量
    life_image1 = pygame.image.load('life_new.png').convert_alpha()
    life_image2 = pygame.image.load('life_new_mate.png').convert_alpha()
    life_rect = life_image1.get_rect()
    # 重生
    invincible_time = 3
    INVINCIBLE_TIME1 = USEREVENT
    INVINCIBLE_TIME2 = USEREVENT + 1
    # 所有敌机
    enemies = pygame.sprite.Group()
    # 生成小型敌机
    small_enemies = pygame.sprite.Group()
    add_small_enemies(small_enemies, enemies, 20)
    # 生成中型敌机
    mid_enemies = pygame.sprite.Group()
    add_mid_enemies(mid_enemies, enemies, 8)
    # 生成大型敌机
    big_enemies = pygame.sprite.Group()
    add_big_enemies(big_enemies, enemies, 2)

    BULLET1_NUM = 4
    BULLET2_NUM = 8
    BULLET3_NUM = 12
    triple_time = 20
    # 生成单发子弹
    bullet1 = []
    bullet1_index = 0
    for i in range(BULLET1_NUM):
        bullet1.append(bullet.Bullet1(me.rect.midtop))
    # 生成双发子弹
    bullet2 = []
    bullet2_index = 0
    for i in range(BULLET2_NUM // 2):
        bullet2.append(bullet.Bullet2((me.rect.centerx - 33, me.rect.centery)))
        bullet2.append(bullet.Bullet2((me.rect.centerx + 30, me.rect.centery)))
    is_double_bullet = False
    # 生成三发子弹
    bullet3 = []
    bullet3_index = 0
    for i in range(BULLET3_NUM // 3):
        bullet3.append(bullet.Bullet3((me.rect.centerx - 33, me.rect.centery)))
        bullet3.append(bullet.Bullet3((me.rect.centerx + 30, me.rect.centery)))
        bullet3.append(bullet.Bullet3(me.rect.midtop))
    TRIPLE_BULLET_TIME1 = USEREVENT + 2
    is_triple_bullet = False

    # 生成单发子弹
    bullet1_mate = []
    bullet1_mate_index = 0
    for i in range(BULLET1_NUM):
        bullet1_mate.append(bullet.Bullet1(me_mate.rect.midtop))
    # 生成双发子弹
    bullet2_mate = []
    bullet2_mate_index = 0
    for i in range(BULLET2_NUM // 2):
        bullet2_mate.append(bullet.Bullet2((me_mate.rect.centerx - 33, me_mate.rect.centery)))
        bullet2_mate.append(bullet.Bullet2((me_mate.rect.centerx + 30, me_mate.rect.centery)))
    is_double_bullet_mate = False
    # 生成三发子弹
    bullet3_mate = []
    bullet3_mate_index = 0
    for i in range(BULLET3_NUM // 3):
        bullet3_mate.append(bullet.Bullet3((me_mate.rect.centerx - 33, me_mate.rect.centery)))
        bullet3_mate.append(bullet.Bullet3((me_mate.rect.centerx + 30, me_mate.rect.centery)))
        bullet3_mate.append(bullet.Bullet3(me_mate.rect.midtop))
    TRIPLE_BULLET_TIME2 = USEREVENT + 3
    is_triple_bullet_mate = False

    # 炸弹
    bomb_image = pygame.image.load('bomb.png').convert_alpha()
    bomb_rect = bomb_image.get_rect()
    bomb_font = pygame.font.Font('font.ttf', 48)
    bomb_num = 3
    BOMB_NUM_MAX = 5
    # 补给
    supply_time1 = 30
    supply_time2 = 18
    supply_time = supply_time2
    bomb_supply = supply.Bomb_Supply(bg_size)
    bullet_supply = supply.Bullet_Supply(bg_size)
    SUPPLY_TIME = USEREVENT + 4
    # 帧率设置
    clock = pygame.time.Clock()
    # 运行
    running = False
    is_start = True
    # 模式
    is_single = False
    # 飞机动画切换
    switch_image = True
    # 延迟
    delay = 100
    # 分数
    score = 0
    score_font = pygame.font.Font('font.ttf', 36)
    # 暂停游戏标志
    paused = False
    pause_nor_image = pygame.image.load('pause_nor.png').convert_alpha()
    pause_pressed_image = pygame.image.load('pause_pressed.png').convert_alpha()
    resume_nor_image = pygame.image.load('resume_nor.png').convert_alpha()
    resume_pressed_image = pygame.image.load('resume_pressed.png').convert_alpha()
    paused_rect = pause_nor_image.get_rect()
    paused_rect.left, paused_rect.top = width - paused_rect.width - 10, 10
    paused_image = pause_nor_image
    # 飞机毁坏图片索引
    e1_destroy_index = 0
    e2_destroy_index = 0
    e3_destroy_index = 0
    me_destroy_index = 0
    me_mate_destroy_index = 0
    # 游戏结束画面
    gameover_font = pygame.font.Font('font.ttf', 48)
    again_image = pygame.image.load('again.png').convert_alpha()
    again_rect = again_image.get_rect()
    gameover_image = pygame.image.load('gameover.png').convert_alpha()
    gameover_rect = gameover_image.get_rect()
    # 难度
    level = 1
    # 封面
    plane1 = myplane.Plane_Gif(bg_size)
    plane2 = myplane.Plane_Gif(bg_size)
    plane3 = myplane.Plane_Gif(bg_size)
    plane3.speed = [0, 10]
    plane3.side = [1, -1]
    while pygame.sprite.collide_mask(plane1, plane2):
        plane2.rect.left, plane2.rect.top = randint(20, bg_size[0] - plane2.rect.width - 10), randint(0, bg_size[
            1] - plane2.rect.height - 10)
    while is_start:
        screen.blit(background, (0, 0))
        mode_choice(screen)
        plane1.move()
        plane2.move()
        plane3.move()
        if pygame.sprite.collide_mask(plane1, plane2):
            plane1.side[0] = -plane1.side[0]
            plane1.side[1] = -plane1.side[1]
            plane2.side[0] = -plane2.side[0]
            plane2.side[1] = -plane2.side[1]
            plane1.speed = [randint(3, 7), randint(3, 7)]
            plane2.speed = [randint(3, 7), randint(3, 7)]
        screen.blit(plane1.image, plane1.rect)
        screen.blit(plane2.image, plane2.rect)
        screen.blit(plane3.image, plane3.rect)
        for event in pygame.event.get():
            if event.type == MOUSEBUTTONDOWN:
                x, y = event.pos[0], event.pos[1]
                if 160 < x < 290 and 220 < y < 280:
                    is_single = True
                    supply_time = supply_time1
                    me_mate.life_num = 0
                    running = True
                    is_start = False
                if 160 < x < 290 and 330 < y < 390:
                    is_single = False
                    supplly_time = supply_time2
                    BOMB_NUM_MAX = 8
                    running = True
                    is_start = False
            elif event.type == KEYDOWN:
                if event.key == K_p:
                    silence = not silence
                    if silence:
                        pygame.mixer.music.pause()
                    else:
                        pygame.mixer.music.play(-1)
            elif event.type == QUIT:
                pygame.quit
                sys.exit()
        pygame.display.flip()
        pygame.time.delay(10)
    # 设置补给计时开始
    pygame.time.set_timer(SUPPLY_TIME, supply_time * 1000)
    while running:
        # 绘制背景
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == MOUSEBUTTONDOWN:
                if event.button == 1 and paused_rect.collidepoint(event.pos):
                    paused = not paused
                    if paused:
                        pygame.time.set_timer(SUPPLY_TIME, 0)
                        pygame.mixer.music.set_volume(0)
                    else:
                        pygame.time.set_timer(SUPPLY_TIME, supply_time * 1000)
                        pygame.mixer.music.set_volume(0.1)
            elif event.type == MOUSEMOTION:
                if paused_rect.collidepoint(event.pos):  # 鼠标移动至图标上，依据是否暂停选择相应的pressed图片
                    if paused:
                        paused_image = resume_pressed_image
                    else:
                        paused_image = pause_pressed_image
                else:  # 鼠标不在图标上，依据是否暂停选择相应的nor图片
                    if paused:
                        paused_image = resume_nor_image
                    else:
                        paused_image = pause_nor_image
            elif event.type == KEYDOWN:
                if event.key == K_SPACE:
                    if bomb_num:
                        bomb_num -= 1
                        if not silence:
                            bomb_sound.play()
                        for each in enemies:
                            if each.rect.bottom > 0:
                                each.active = False
                                if each in small_enemies:
                                    score += 1000
                                elif each in mid_enemies:
                                    score += 5000
                                elif each in big_enemies:
                                    score += 10000
                elif event.key == K_o:
                    paused = not paused
                    if paused:
                        pygame.time.set_timer(SUPPLY_TIME, 0)
                        pygame.mixer.music.set_volume(0)
                    else:
                        pygame.time.set_timer(SUPPLY_TIME, supply_time * 1000)
                        pygame.mixer.music.set_volume(0.2)
                elif event.key == K_p:
                    silence = not silence
                    if silence:
                        pygame.mixer.music.pause()
                        bullet_sound.stop()
                        enemy3_fly_sound.stop()
                    else:
                        pygame.mixer.music.play(-1)

            elif event.type == SUPPLY_TIME:
                if not silence:
                    supply_sound.play()
                if choice([True, False]):
                    bomb_supply.reset()
                else:
                    bullet_supply.reset()
            elif event.type == TRIPLE_BULLET_TIME1:
                is_triple_bullet = False
                pygame.time.set_timer(TRIPLE_BULLET_TIME1, 0)
            elif event.type == TRIPLE_BULLET_TIME2:
                is_triple_bullet_mate = False
                pygame.time.set_timer(TRIPLE_BULLET_TIME2, 0)
            elif event.type == INVINCIBLE_TIME1:
                me.invincible = False
                pygame.time.set_timer(INVINCIBLE_TIME1, 0)
            elif event.type == INVINCIBLE_TIME2:
                me_mate.invincible = False
                pygame.time.set_timer(INVINCIBLE_TIME2, 0)
        screen.blit(background, (0, 0))
        if me.life_num + me_mate.life_num > 0 and not paused:
            # 手势检测
            if GESTURE_MODE:
                # print(up,down,left,right)
                if is_single:
                    # print(up,down,left,right)
                    if up > 0:
                        me.moveUp(up)
                    if down < 0:
                        me.moveDown(abs(down))
                    if left > 0:
                        me.moveLeft(left)
                    if right < 0:
                        me.moveRight(abs(right))
                else:
                    if up > 0:
                        me.moveUp(up)
                    if down < 0:
                        me.moveDown(abs(down))
                    if left > 0:
                        me.moveLeft(left)
                    if right < 0:
                        me.moveRight(abs(right))

                    if up_3 > 0:
                        me_mate.moveUp(up_3)
                    if down_3 < 0:
                        me_mate.moveDown(abs(down_3))
                    if left_3 > 0:
                        me_mate.moveLeft(left_3)
                    if right_3 < 0:
                        me_mate.moveRight(abs(right_3))

                    # bomb
                    global count_boom
                    global gap

                    if count_boom >= 5:
                        count_boom = 0
                        if bomb_num:
                            gap = 0
                            bomb_num -= 1
                            for each in enemies:
                                if each.rect.bottom > 0:
                                    each.active = False
                                    if each in small_enemies:
                                        score += 1000
                                    elif each in mid_enemies:
                                        score += 5000
                                    elif each in big_enemies:
                                        score += 10000
            # 方向按键检测
            key_pressed = pygame.key.get_pressed()
            if is_single:
                if key_pressed[K_w] or key_pressed[K_UP]:
                    me.moveUp()
                if key_pressed[K_s] or key_pressed[K_DOWN]:
                    me.moveDown()
                if key_pressed[K_a] or key_pressed[K_LEFT]:
                    me.moveLeft()
                if key_pressed[K_d] or key_pressed[K_RIGHT]:
                    me.moveRight()
            else:
                if key_pressed[K_w]:
                    me_mate.moveUp()
                if key_pressed[K_s]:
                    me_mate.moveDown()
                if key_pressed[K_a]:
                    me_mate.moveLeft()
                if key_pressed[K_d]:
                    me_mate.moveRight()
                if key_pressed[K_UP]:
                    me.moveUp()
                if key_pressed[K_DOWN]:
                    me.moveDown()
                if key_pressed[K_LEFT]:
                    me.moveLeft()
                if key_pressed[K_RIGHT]:
                    me.moveRight()
            # 飞机动画设置
            if not (delay % 5):
                switch_image = not switch_image
            delay -= 1
            if not delay:
                delay = 100
            # 子弹动画设置
            if not (delay % 9):
                if not silence:
                    bullet_sound.play()
                if is_double_bullet:
                    if is_triple_bullet:
                        bullets = bullet3
                        bullets[bullet3_index].reset((me.rect.centerx - 33, me.rect.centery))
                        bullets[bullet3_index + 1].reset((me.rect.centerx + 30, me.rect.centery))
                        bullets[bullet3_index + 2].reset(me.rect.midtop)
                        bullet3_index = (bullet3_index + 3) % BULLET3_NUM
                    else:
                        bullets = bullet2
                        bullets[bullet2_index].reset((me.rect.centerx - 33, me.rect.centery))
                        bullets[bullet2_index + 1].reset((me.rect.centerx + 30, me.rect.centery))
                        bullet2_index = (bullet2_index + 2) % BULLET2_NUM
                else:
                    bullets = bullet1
                    bullets[bullet1_index].reset(me.rect.midtop)
                    bullet1_index = (bullet1_index + 1) % BULLET1_NUM
                if me.life_num == 0:
                    bullets = []
                if not is_single:
                    if is_double_bullet_mate:
                        if is_triple_bullet_mate:
                            bullets_mate = bullet3_mate
                            bullets_mate[bullet3_mate_index].reset((me_mate.rect.centerx - 33, me_mate.rect.centery))
                            bullets_mate[bullet3_mate_index + 1].reset(
                                (me_mate.rect.centerx + 30, me_mate.rect.centery))
                            bullets_mate[bullet3_mate_index + 2].reset(me_mate.rect.midtop)
                            bullet3_mate_index = (bullet3_mate_index + 3) % BULLET3_NUM
                        else:
                            bullets_mate = bullet2_mate
                            bullets_mate[bullet2_mate_index].reset((me_mate.rect.centerx - 33, me_mate.rect.centery))
                            bullets_mate[bullet2_mate_index + 1].reset(
                                (me_mate.rect.centerx + 30, me_mate.rect.centery))
                            bullet2_mate_index = (bullet2_mate_index + 2) % BULLET2_NUM
                    else:
                        bullets_mate = bullet1_mate
                        bullets_mate[bullet1_mate_index].reset(me_mate.rect.midtop)
                        bullet1_mate_index = (bullet1_mate_index + 1) % BULLET1_NUM
                    if me_mate.life_num == 0:
                        bullets_mate = []
            # 绘制子弹并检测击中敌机，完成加分
            if len(bullets) > 0:
                for b in bullets:
                    if b.active:
                        b.move()
                        screen.blit(b.image, b.rect)
                        enemy_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
                        if enemy_hit:
                            b.active = False
                            for e in enemy_hit:
                                if e.rect.bottom >= 0:
                                    if e in mid_enemies or e in big_enemies:
                                        e.energy -= 1
                                        e.hit = True
                                        if e.energy == 0:
                                            e.active = False
                                    else:
                                        e.active = False
            if not is_single and len(bullets_mate) > 0:
                for b in bullets_mate:
                    if b.active:
                        b.move()
                        screen.blit(b.image, b.rect)
                        enemy_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)
                        if enemy_hit:
                            b.active = False
                            for e in enemy_hit:
                                if e.rect.bottom >= 0:
                                    if e in mid_enemies or e in big_enemies:
                                        e.energy -= 1
                                        e.hit = True
                                        if e.energy == 0:
                                            e.active = False
                                    else:
                                        e.active = False
            # 绘制大型敌机
            for each in big_enemies:
                if each.active:
                    each.move()
                    if each.hit:
                        screen.blit(each.image_hit, each.rect)
                        each.hit = False
                    else:
                        if switch_image:
                            screen.blit(each.image1, each.rect)
                        else:
                            screen.blit(each.image2, each.rect)
                    # 绘制血槽
                    pygame.draw.line(screen, BLACK, (each.rect.left, each.rect.top - 5),
                                     (each.rect.right, each.rect.top - 5), 2)
                    energy_remain = each.energy / enemy.BigEnemy.energy
                    if energy_remain > 0.2:
                        energy_color = GREEN
                    else:
                        energy_color = RED
                    pygame.draw.line(screen, energy_color, (each.rect.left, each.rect.top - 5),
                                     (each.rect.left + each.rect.width * energy_remain, each.rect.top - 5), 2)
                    if each.rect.bottom > -50 and not silence:
                        enemy3_fly_sound.play()
                else:
                    if not (delay % 3):
                        if e3_destroy_index == 0 and not silence:
                            enemy3_fly_sound.stop()
                            enemy3_down_sound.play()
                        screen.blit(each.destroy_images[e3_destroy_index], each.rect)
                        e3_destroy_index = (e3_destroy_index + 1) % 6
                        if e3_destroy_index == 0:
                            each.reset()
                            if not silence:
                                enemy3_down_sound.stop()
                            score += 10000
            # 绘制中型敌机
            for each in mid_enemies:
                if each.active:
                    each.move()
                    if each.hit:
                        screen.blit(each.image_hit, each.rect)
                        each.hit = False
                    else:
                        screen.blit(each.image, each.rect)
                    # 绘制血槽
                    pygame.draw.line(screen, BLACK, (each.rect.left, each.rect.top - 5),
                                     (each.rect.right, each.rect.top - 5), 2)
                    energy_remain = each.energy / enemy.MidEnemy.energy
                    if energy_remain > 0.2:
                        energy_color = GREEN
                    else:
                        energy_color = RED
                    pygame.draw.line(screen, energy_color, (each.rect.left, each.rect.top - 5),
                                     (each.rect.left + each.rect.width * energy_remain, each.rect.top - 5), 2)
                else:
                    if not (delay % 3):
                        if e2_destroy_index == 0 and not silence:
                            enemy2_down_sound.play()
                        screen.blit(each.destroy_images[e2_destroy_index], each.rect)
                        e2_destroy_index = (e2_destroy_index + 1) % 4
                        if e2_destroy_index == 0:
                            each.reset()
                            if not silence:
                                enemy2_down_sound.stop()
                            score += 5000
            # 绘制小型敌机
            for each in small_enemies:
                if each.active:
                    each.move()
                    screen.blit(each.image, each.rect)
                else:
                    if not (delay % 3):
                        if e1_destroy_index == 0 and not silence:
                            enemy1_down_sound.play()
                        screen.blit(each.destroy_images[e1_destroy_index], each.rect)
                        e1_destroy_index = (e1_destroy_index + 1) % 4
                        if e1_destroy_index == 0:
                            if not silence:
                                enemy1_down_sound.stop()
                            each.reset()
                            score += 1000
            # 检测飞机碰撞敌机
            me_collided = False
            if me.life_num > 0:
                enemies_down = pygame.sprite.spritecollide(me, enemies, False, pygame.sprite.collide_mask)
                if enemies_down and not me.invincible:
                    me.active = False
                    me_collided = True
                    for e in enemies_down:
                        e.active = False

            if not is_single and me_mate.life_num > 0:
                mate_enemies_down = pygame.sprite.spritecollide(me_mate, enemies, False, pygame.sprite.collide_mask)
                if mate_enemies_down and not me_mate.invincible and not me_collided:
                    me_mate.active = False
                    for e in mate_enemies_down:
                        e.active = False
            # 绘制己方飞机
            if me.active:
                if switch_image:
                    screen.blit(me.image1, me.rect)
                else:
                    screen.blit(me.image2, me.rect)
                if not is_single:
                    screen.blit(me_number, (me.rect.midtop[0] - 2, me.rect.midtop[1] + 5))
            elif me.life_num > 0:
                if not (delay % 3):
                    if me_destroy_index == 0 and not silence:
                        me_down_sound.play()
                    screen.blit(me.destroy_images[me_destroy_index], me.rect)
                    me_destroy_index = (me_destroy_index + 1) % 4
                    if me_destroy_index == 0:
                        me.life_num -= 1
                        me.reset(bg_size)
                        is_double_bullet = False
                        is_triple_bullet = False
                        pygame.time.set_timer(INVINCIBLE_TIME1, invincible_time * 1000)
            else:
                pass
            if not is_single:
                if me_mate.active:
                    if switch_image:
                        screen.blit(me_mate.image1, me_mate.rect)
                    else:
                        screen.blit(me_mate.image2, me_mate.rect)
                    screen.blit(mate_number, (me_mate.rect.midtop[0] - 2, me_mate.rect.midtop[1] + 5))
                elif me_mate.life_num > 0:
                    if not (delay % 3):
                        if me_mate_destroy_index == 0 and not silence:
                            me_down_sound.play()
                        screen.blit(me_mate.destroy_images[me_mate_destroy_index], me_mate.rect)
                        me_mate_destroy_index = (me_mate_destroy_index + 1) % 4
                        if me_mate_destroy_index == 0:
                            me_mate.life_num -= 1
                            me_mate.reset()
                            is_double_bullet_mate = False
                            is_triple_bullet_mate = False
                            pygame.time.set_timer(INVINCIBLE_TIME2, invincible_time * 1000)
                else:
                    pass
            # 绘制生命数量
            if me.life_num > 0:
                for i in range(me.life_num):
                    screen.blit(life_image1, (width - 10 - (i + 1) * life_rect.width, height - 10 - life_rect.height))
                if not is_single:
                    screen.blit(me_number, (width - 17 - me.life_num * life_rect.width, height - 10 - life_rect.height))
            if me_mate.life_num > 0 and not is_single:
                for i in range(me_mate.life_num):
                    screen.blit(life_image2, (width - 25 - life_rect.width * me.life_num - (i + 1) * life_rect.width,
                                              height - 10 - life_rect.height))
                screen.blit(mate_number, (
                width - 29 - (me.life_num + me_mate.life_num) * life_rect.width, height - 10 - life_rect.height))
            # 绘制全屏炸弹
            bomb_text = bomb_font.render('X %d' % bomb_num, True, WHITE)
            text_rect = bomb_text.get_rect()
            screen.blit(bomb_image, (10, height - 10 - bomb_rect.height))
            screen.blit(bomb_text, (20 + bomb_rect.width, height - text_rect.height - 5))
            # 绘制补给
            if bomb_supply.active:
                bomb_supply.move()
                me_get = False
                screen.blit(bomb_supply.image, bomb_supply.rect)
                if pygame.sprite.collide_mask(bomb_supply, me) and me.life_num > 0:
                    if not silence:
                        get_bomb_sound.play()
                    if bomb_num < BOMB_NUM_MAX:
                        bomb_num += 1
                    bomb_supply.active = False
                    me_get = True
                if pygame.sprite.collide_mask(bomb_supply, me_mate) and not is_single and me_mate.life_num > 0:
                    if not silence:
                        get_bomb_sound.play()
                    if bomb_num < BOMB_NUM_MAX and not me_get:
                        bomb_num += 1
                    bomb_supply.active = False
                    me_get = False
            if bullet_supply.active:
                bullet_supply.move()
                screen.blit(bullet_supply.image, bullet_supply.rect)
                me_get = False
                if pygame.sprite.collide_mask(bullet_supply, me) and me.life_num > 0:
                    if not silence:
                        get_bullet_sound.play()
                    bullet_supply.active = False
                    if not is_double_bullet:
                        is_double_bullet = True
                    else:
                        is_triple_bullet = True
                    me_get = True
                    pygame.time.set_timer(TRIPLE_BULLET_TIME1, triple_time * 1000)
                if pygame.sprite.collide_mask(bullet_supply, me_mate) and not is_single and me_mate.life_num > 0:
                    if not me_get:
                        if not silence:
                            get_bullet_sound.play()
                        bullet_supply.active = False
                        if not is_double_bullet_mate:
                            is_double_bullet_mate = True
                        else:
                            is_triple_bullet_mate = True
                        pygame.time.set_timer(TRIPLE_BULLET_TIME2, triple_time * 1000)
                    else:
                        me_get = False
            if me.life_num == 0:
                pygame.time.set_timer(TRIPLE_BULLET_TIME1, 0)
                pygame.time.set_timer(INVINCIBLE_TIME1, 0)
                me.active = False
                me_collided = False
            if me_mate.life_num == 0 and not is_single:
                pygame.time.set_timer(TRIPLE_BULLET_TIME2, 0)
                pygame.time.set_timer(INVINCIBLE_TIME2, 0)
                me_mate.active = False
        elif me.life_num == 0 and me_mate.life_num == 0:  # 游戏结束
            pygame.time.set_timer(SUPPLY_TIME, 0)

            with open('record1.txt', 'r') as f:
                try:
                    record_score1 = int(f.read())
                except ValueError:
                    record_score1 = 0
            with open('record2.txt', 'r') as f:
                try:
                    record_score2 = int(f.read())
                except ValueError:
                    record_score2 = 0
            if is_single and score >= record_score1:
                with open('record1.txt', 'w') as f:
                    f.write(str(score))
            if not is_single and score >= record_score2:
                with open('record2.txt', 'w') as f:
                    f.write(str(score))
            # 绘制纪录
            record_score_text1 = score_font.render('Best(single): %d' % record_score1, True, WHITE)
            record_score_text2 = score_font.render('Best(double): %d' % record_score2, True, WHITE)
            screen.blit(record_score_text1, (50, 50))
            screen.blit(record_score_text2, (50, 100))
            # 绘制YourScore文字
            gameover_text1 = gameover_font.render('Your Score', True, WHITE)
            gameover_text1_rect = gameover_text1.get_rect()
            gameover_text1_rect.left, gameover_text1_rect.top = (width - gameover_text1_rect.width) // 2, height // 3
            screen.blit(gameover_text1, gameover_text1_rect)
            # 绘制YourScore数字
            gameover_text2 = gameover_font.render(str(score), True, WHITE)
            gameover_text2_rect = gameover_text2.get_rect()
            gameover_text2_rect.left, gameover_text2_rect.top = (
            width - gameover_text2_rect.width) // 2, gameover_text1_rect.bottom + 10
            screen.blit(gameover_text2, gameover_text2_rect)
            # 绘制重新开始按钮
            again_rect.left, again_rect.top = (width - again_rect.width) // 2, gameover_text2_rect.bottom + 50
            screen.blit(again_image, again_rect)
            gameover_rect.left, gameover_rect.top = (width - gameover_rect.width) // 2, again_rect.bottom + 10
            screen.blit(gameover_image, gameover_rect)
            # 检测鼠标操作
            if pygame.mouse.get_pressed()[0]:
                pos = pygame.mouse.get_pos()
                if again_rect.left < pos[0] < again_rect.right and again_rect.top < pos[1] < again_rect.bottom:
                    enemy.MidEnemy.energy = 10
                    enemy.BigEnemy.energy = 25
                    plane_main()
                elif gameover_rect.left < pos[0] < gameover_rect.right and gameover_rect.top < pos[1] < \
                        gameover_rect.bottom:
                    pygame.quit()
                    sys.exit()
        if me.life_num > 0 or me_mate.life_num > 0:
            # 绘制暂停按钮
            screen.blit(paused_image, paused_rect)
            # 绘制得分
            score_text = score_font.render('Score : %s' % str(score), True, WHITE)
            screen.blit(score_text, (10, 5))
        pygame.display.flip()
        clock.tick(60)
        # 设置游戏难度（飞机数量及速度）
        if level == 1 and score >= 50000:
            level = 2
            if not silence:
                upgrade_sound.play()
            add_small_enemies(small_enemies, enemies, 3)
            add_mid_enemies(mid_enemies, enemies, 1)
            enemy.BigEnemy.energy += 5
            if not is_single:
                inc_speed(small_enemies, 1)
                enemy.MidEnemy.energy += 2
        elif level == 2 and score >= 200000:
            level = 3
            if not silence:
                upgrade_sound.play()
            add_small_enemies(small_enemies, enemies, 3)
            add_mid_enemies(mid_enemies, enemies, 2)
            add_big_enemies(big_enemies, enemies, 1)
            inc_speed(small_enemies, 1)
            enemy.MidEnemy.energy += 1
            enemy.BigEnemy.energy += 5
        elif level == 3 and score >= 500000:
            level = 4
            if not silence:
                upgrade_sound.play()
            add_small_enemies(small_enemies, enemies, 4)
            add_mid_enemies(mid_enemies, enemies, 3)
            add_big_enemies(big_enemies, enemies, 1)
            inc_speed(mid_enemies, 1)
            enemy.MidEnemy.energy += 1
            enemy.BigEnemy.energy += 5
        elif level == 4 and score >= 1000000:
            level = 5
            if not silence:
                upgrade_sound.play()
            add_small_enemies(small_enemies, enemies, 5)
            add_mid_enemies(mid_enemies, enemies, 3)
            add_big_enemies(big_enemies, enemies, 2)
            inc_speed(small_enemies, 1)
            enemy.BigEnemy.energy += 5
            enemy.MidEnemy.energy += 2
            if not is_single:
                inc_speed(big_enemies, 1)
        elif level == 5 and score >= 2000000:
            level = 6
            if not silence:
                upgrade_sound.play()
            inc_speed(big_enemies, 1)
            add_mid_enemies(mid_enemies, enemies, 3)
            if not is_single:
                add_mid_enemies(mid_enemies, enemies, 2)
                add_big_enemies(big_enemies, enemies, 2)


# AGENT

broker_ip = sys.argv[1]
threshold = 5  # 响应阈值
# agent_id = int(sys.argv[2])
agent_id = 1


def decode(x_rotation, y_rotation, sender_id, x_gyro_scaled):
    # x_distance, y_distance, rotation = -50, 50, 1
    global up
    global down
    global left
    global right
    global boom_value

    global up_3
    global down_3
    global left_3
    global right_3
    global boom_3_value

    global count_boom
    global gap

    # Calculate by x_rotation, y_rotation, can be extended to velocity.

    if sender_id == 2:
        # Calculate by x_rotation, y_rotation, can be extended to velocity.
        up, down, left, right = (y_rotation - threshold), \
                                (y_rotation + threshold), \
                                (x_rotation - threshold), \
                                (x_rotation + threshold)
        boom_value = x_gyro_scaled

    else:
        # Calculate by x_rotation, y_rotation, can be extended to velocity.
        up_3, down_3, left_3, right_3 = (y_rotation - threshold), \
                                        (y_rotation + threshold), \
                                        (x_rotation - threshold), \
                                        (x_rotation + threshold)
        boom_3_value = x_gyro_scaled

    if gap > 5:
        if abs(boom_value) >= 150 and abs(boom_3_value) >= 150:
            count_boom += 1
        else:
            count_boom = 0
    else:
        gap += 1

    print("gap: ", gap)

    # print("------------boom_value: ", boom_value)
    # print("------------boom_3_value: ", boom_3_value)
    # print("----------------count_boom: ", count_boom)
    # print()


def agent_out():
    context = zmq.Context()
    publisher = context.socket(zmq.PUB)
    publisher.connect("tcp://%s:5556" % broker_ip)

    subscriber = context.socket(zmq.SUB)
    subscriber.connect("tcp://%s:5555" % broker_ip)
    subscriber.setsockopt_string(zmq.SUBSCRIBE, str(agent_id))
    while True:
        # recv data of hand moving, output to screen
        if agent_id == 1:
            message = subscriber.recv()
            # print("message received")
            # data format: float x:float y, for example: -5.5195:-9.3865
            rotation = str(message, encoding="utf8")
            # print(rotation)
            _, x_rotation, y_rotation, sender_id, x_gyro_scaled = rotation.split(':')
            # print('%s:%s:%s:%s' % (sender_id, x_rotation, y_rotation, x_gyro_scaled))
            decode(float(x_rotation), float(y_rotation), int(sender_id), float(x_gyro_scaled))  # direction vector is global.

        # wrong agent ID!
        else:
            print("wrong agent ID!")

# 创建 Thread 实例
# END OF AGENT


if __name__ == "__main__":
    try:
        # 创建 Thread 实例
        t1 = Thread(target=agent_out)
        t2 = Thread(target=plane_main)

        # 启动线程运行
        t1.start()
        t2.start()

        # 等待所有线程执行完毕
        t1.join()  # join() 等待线程终止，要不然一直挂起
        t2.join()
    except SystemExit:
        pygame.quit()
        for each in pics:
            os.remove(each)
